package com.entity.implement;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.common.ObjectIdUtil;
import com.entity.myInterface.UserRepositoryCustom;
import com.entity.paging.UserSearchCondition;
import com.okok.entity.User;
import com.shiro.entity.Role;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import com.mongodb.DBRef;



@Repository
public class UserRepositoryImpl implements UserRepositoryCustom {
	
	private static Logger logger = LoggerFactory
			.getLogger(UserRepositoryImpl.class);
	
	@Autowired
	private MongoTemplate mongoTemplate;
	
	@Override
	public Page<User> search(int pageNo, int pageSize, String condition, String app) {
		
		Query query = new Query();
		
		Criteria criteria = Criteria.where("delflag").is(false).and("app").is(app);
		if (null != condition && !"".equals(condition)){
			criteria.and("name").regex(condition);
		}
		
		Pageable pageable = PageRequest.of(pageNo - 1, pageSize);

		query.addCriteria(criteria);
		long total = mongoTemplate.count(query, User.class);

		query.skip(pageable.getOffset());
		query.limit(pageable.getPageSize());
		query.with(new Sort(Direction.ASC,"lgoinName"));

		List<User> items = mongoTemplate.find(query,User.class);

		if (items == null) {
			return null;
		}

		PageImpl<User> page = new PageImpl<User>(items,
				pageable, total);

		return page;
	}

	@Override
	public List<User> findBy(String username, String phone) {
		Query query = new Query();

		Criteria criteria = new Criteria();
		criteria.and("username").is(username);
		criteria.and("phone").is(phone);
		query.addCriteria(criteria);

		return mongoTemplate.find(query, User.class);
	}


	@Override
	public User findByIdd(String id) {
		Query query = new Query();

		Criteria criteria = new Criteria();
		criteria.and("id").is(new ObjectId(id));
		query.addCriteria(criteria);

		return mongoTemplate.findOne(query, User.class);
	}

	/**
	 * 
	 * @Description:删除
	 * @param id
	 * @param op
	 * @Author wendel
	 * @Date:2017年3月15日
	 */
	@Override
	public void delete(String id, String op) {
		Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        logger.info("delfag:");
        Update update = new Update();
        update.set("delflag", true);
        update.set("modifier", op);
        update.set("modifyDate", new Date());
        
        mongoTemplate.updateFirst(query, update, User.class);
	}
	
	@Override
	public Page<User> findByPage(UserSearchCondition rsc){
		
		Query query = new Query();
		Criteria criteria = Criteria.where("delflag").is(false);
		
		String pattern = "^.*%s.*$";
		
		if (!CollectionUtils.isEmpty(rsc.getUserIds())) {
			criteria.and("_id").in(ObjectIdUtil.buildObjectIds(rsc.getUserIds()));
		}
		if(StringUtils.isNotBlank(rsc.getLoginName())){
			criteria.and("loginName").regex(String.format(pattern, rsc.getLoginName()));
		}
		if(StringUtils.isNotBlank(rsc.getPhone())){
			criteria.and("phone").regex(String.format(pattern, rsc.getPhone()));
		}
		if(StringUtils.isNotBlank(rsc.getContact())){
			criteria.and("contact").regex(String.format(pattern, rsc.getContact()));
		}
		if(StringUtils.isNotBlank(rsc.getEmail())){
			criteria.and("email").regex(String.format(pattern, rsc.getEmail()));
		}
		
		if(StringUtils.isNotBlank(rsc.getRoleId())){
			criteria.orOperator(
					Criteria.where("roles").all(new DBRef("role", new ObjectId(rsc.getRoleId()))),
					Criteria.where("roles").elemMatch(Criteria.where("_id").is(new ObjectId(rsc.getRoleId())))
					);
		}
		if(StringUtils.isNotBlank(rsc.getApp())){
			criteria.and("app").is(rsc.getApp());
		}
		
		// or查询
		if (StringUtils.isNotBlank(rsc.getSearcword())){
			criteria.orOperator(
					Criteria.where("loginName").regex(String.format(pattern, rsc.getSearcword())),
					Criteria.where("phone").regex(String.format(pattern, rsc.getSearcword())),
					Criteria.where("contact").regex(String.format(pattern, rsc.getSearcword()))
					);
		}
		// 各种分页相关设置
		Pageable pageable =  PageRequest.of(rsc.getPageNo() - 1, rsc.getPageSize());
		query.addCriteria(criteria);
		// 查询数据记录总数
		long total = mongoTemplate.count(query, User.class);
		query.skip(pageable.getOffset());
		query.limit(pageable.getPageSize());
		query.with(new Sort(Direction.DESC,"_id"));
		// 查询到当页数据
		List<User> users = mongoTemplate.find(query, User.class);
		
		if(users == null){
			logger.info("查询失败");
			return null;
		}
		
		PageImpl<User> page = new PageImpl<User>(users, pageable, total);

		return page;
	}
	
	@Override
	public User findByMobilPhone(String mobilPhone) {
		Query query = new Query();

		Criteria criteria = new Criteria();
		criteria.and("phone").is(mobilPhone);
		query.addCriteria(criteria);

		return mongoTemplate.findOne(query, User.class);
	}
	
	@Override
	public void update(User user,String op){
		Query query=new Query();
		query.addCriteria(Criteria.where("id").is(user.getId()));
		
		Update update = new Update();
		update.set("modifier", op);
		update.set("modifyDate", new Date());
		
		/*if(StringUtils.isNotBlank(user.getLoginName())){
			update.set("loginName", user.getLoginName());
		}
		if(StringUtils.isNotBlank(user.getPlainPassword())){
			update.set("plainPassword", user.getPlainPassword());
		}*/
		/*if(StringUtils.isNotBlank(user.getClientId())){
			update.set("clientId",user.getClientId());
		}*/
		/*if(StringUtils.isNotBlank(user.getName())){
			update.set("name", user.getName());
		}*/
		/*if(user.getRoles()!=null){
			update.set("roles", user.getRoles());
		}*/
		if(StringUtils.isNotBlank(user.getApp())){
			update.set("app", user.getApp());
		}
		mongoTemplate.updateFirst(query, update, User.class);
	}

	@Override
	public List<User> findAllNotDel() {
		Query query = new Query();
		query.addCriteria(Criteria.where("delflag").is(false));
		return mongoTemplate.find(query, User.class);
	}
	
	@Override
	public User findByLoginName(String loginName) {
		Query query = new Query();

		Criteria criteria = new Criteria();
		criteria.and("loginName").is(loginName).and("delflag").is(false);
		query.addCriteria(criteria);

		return mongoTemplate.findOne(query, User.class);
	}
	@Override
	public void updateDesc(String id, String desc, String op){
		Query query=new Query();
		query.addCriteria(Criteria.where("id").is(id));
		
		Update update = new Update();
		update.set("modifier", op);
		update.set("modifyDate", new Date());
		
		update.set("desc", desc);
			
		mongoTemplate.updateFirst(query, update, User.class);
	}
	@Override
	public List<User> findByRoleIsAdmin(Role role) {
		Query query = new Query();
		query.addCriteria(Criteria.where("delflag").is(false).and("roles.$id").in(new ObjectId(role.getId())));
		return mongoTemplate.find(query, User.class);
	}
	
	@Override
	public void updateEdit(String id, String loginName,String abbreviation,String company,
			String companyAddr,String contact,String phone,String email,String qq,String weixin,String op){
		Query query=new Query();
		query.addCriteria(Criteria.where("id").is(id));
		
		Update update = new Update();
		update.set("modifier", op);
		update.set("modifyDate", new Date());
		
		if(StringUtils.isNotBlank(loginName)){
			update.set("loginName", loginName);
		}
		if(StringUtils.isNotBlank(abbreviation)){
			update.set("abbreviation", abbreviation);
		}
		if(StringUtils.isNotBlank(company)){
			update.set("company", company);
		}
		if(StringUtils.isNotBlank(companyAddr)){
			update.set("companyAddr", companyAddr);
		}
		if(StringUtils.isNotBlank(contact)){
			update.set("contact", contact);
		}
		if(StringUtils.isNotBlank(phone)){
			update.set("phone", phone);
		}
		if(StringUtils.isNotBlank(email)){
			update.set("email", email);
		}
		if(StringUtils.isNotBlank(qq)){
			update.set("qq", qq);
		}
		if(StringUtils.isNotBlank(weixin)){
			update.set("weixin", weixin);
		}	
		mongoTemplate.updateFirst(query, update, User.class);
	}

	@Override
	public User findByEmail(String email) {
		Query query = new Query();
		query.addCriteria(Criteria.where("delflag").is(false).and("email").is(email));
		return mongoTemplate.findOne(query, User.class);
	}
	
	@Override
	public void updateTimeStampById(String id, String linkTimeStamp, String op) {
		Query query = new Query();
		query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
		Update update = new Update();
		update.set("linkTimeStamp", linkTimeStamp);
		update.set("modifier",op);
		update.set("modifyDate", new Date());
		mongoTemplate.updateFirst(query, update, User.class);
	}

	@Override
	public void updateRolesById(List<Role> roles, String id,String op) {
		Query query = new Query();
		query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
		Update update = new Update();
		List<DBRef> roleDbRefs = new ArrayList<DBRef>();
		if (!CollectionUtils.isEmpty(roles)) {
			for (Role role : roles) {
				roleDbRefs.add(new DBRef("role", new ObjectId(role.getId())));
			}
		}
		update.set("roles", roleDbRefs);
		update.set("modifyDate", new Date());
		update.set("modifier", op);
		mongoTemplate.updateFirst(query, update, User.class);
	}

	@Override
	public List<User> findByRoleId(String roleId) {
		Query query = new Query();
		Criteria criteria = Criteria.where("delflag").is(false);
		//criteria.and("roles.$id").in(new ObjectId(roleId));
		criteria.orOperator(
				Criteria.where("roles").all(new DBRef("role", new ObjectId(roleId))),
				Criteria.where("roles").elemMatch(Criteria.where("_id").is(new ObjectId(roleId)))
				);
		query.addCriteria(criteria);
		return mongoTemplate.find(query, User.class);
	}



	@Override
	public void updateBaseInfo(String id, String contact, String phone, String email,
			String qq, String weixin, String op) {
		Query query = new Query();
		query.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
		Update update = new Update();
		if (StringUtils.isNotBlank(contact)) {
			update.set("contact", contact);
		}
		if (StringUtils.isNotBlank(phone)) {
			update.set("phone", phone);
		}
		if (StringUtils.isNotBlank(email)) {
			update.set("email", email);
		}
		if (StringUtils.isNotBlank(qq)) {
			update.set("qq", qq);
		}
		if (StringUtils.isNotBlank(weixin)) {
			update.set("weixin", weixin);
		}
		update.set("modifier", op);
		update.set("modifyDate", new Date());
		mongoTemplate.updateFirst(query, update, User.class);
		
	}

	@Override
	public void updateClientId(String id, String clientId, String op) {
		Query query = new Query();
		Criteria criteria = Criteria.where("_id").is(new ObjectId(id));
		query.addCriteria(criteria);
		
		Update update = new Update();
		update.set("clientId", clientId);
		update.set("modifier", op);
		update.set("modifyDate", new Date());
		mongoTemplate.updateFirst(query, update, User.class);
	}


	@Override
	public List<User> findByLikeLoginName(String loginName) {
		Query query = new Query();
		String pattern = "^.*%s.*$";

		Criteria criteria = new Criteria();
		criteria.and("loginName").regex(String.format(pattern, loginName))
			.and("delflag").is(false);
		query.addCriteria(criteria);

		return mongoTemplate.find(query, User.class);
	}
	
	@Override
	public List<User> findByRoleIsCsAndCityId(Role role,String cityId) {
		Query query = new Query();
		Criteria criteria = Criteria.where("delflag").is(false).and("roles").all(new DBRef("role", new ObjectId(role.getId())));
		criteria.and("cscitys").all(new DBRef("city", new ObjectId(cityId)));
		query.addCriteria(criteria);
		return mongoTemplate.find(query, User.class);
	}

	@Override
	public List<User> findMyUsers(List<String> userIds, String searchWord) {
		Query query = new Query();
		Criteria criteria = Criteria.where("delflag").is(false)
				.and("_id").in(ObjectIdUtil.buildObjectIds(userIds));
		String pattern = "^.*%s.*$";
		if (StringUtils.isNotBlank(searchWord)) {
			criteria.orOperator(
					Criteria.where("loginName").regex(String.format(pattern, searchWord)),
					Criteria.where("name").regex(String.format(pattern, searchWord)),
					Criteria.where("abbreviation").regex(String.format(pattern, searchWord))
					);
		}
		query.addCriteria(criteria);
		return mongoTemplate.find(query, User.class);
	}

	@Override
	public List<User> findByIds(List<String> ids) {
		Query query = new Query();
		Criteria criteria = Criteria.where("delflag").is(false)
				.and("_id").in(ObjectIdUtil.buildObjectIds(ids));
		query.addCriteria(criteria);
		return mongoTemplate.find(query, User.class);
	}

	@Override
	public void updateMobileOs(String id, String os, String op) {
		Query query = new Query();
		Criteria criteria = Criteria.where("_id").is(new ObjectId(id));
		query.addCriteria(criteria);
		
		Update update = new Update();
		update.set("mobileOs", os);
		update.set("modifier", op);
		update.set("modifyDate", new Date());
		mongoTemplate.updateFirst(query, update, User.class);
	}

}